package com.edu.dk.security.impl;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.edu.dk.security.WebContext;
import com.edu.dk.security.util.StringUtils;

/**
 * Usage:<br/>
 * 
 * <filter> <filter-name>MyFilter</filter-name>
 * <filter-class>com.edu.dk.security.impl.HttpFilter</filter-class> </filter>
 * 
 * <filter-mapping> <filter-name>MyFilter</filter-name>
 * <url-pattern>/*</url-pattern> <dispatcher>REQUEST</dispatcher>
 * <dispatcher>FORWARD</dispatcher> </filter-mapping>
 * 
 */
public class HttpFilter implements Filter {
	public static final String REQUEST_CONTEXT_KEY = "_outer_webx3_request_context_";
	public static final String TINY_CONTEXT_PATH = "TINY_CONTEXT_PATH";
	public static final String TINY_REQUEST_URI = "TINY_REQUEST_URI";
	public static final String TINY_SERVLET_PATH = "TINY_SERVLET_PATH";

	public static final String DEFAULT_PAGE_KEY = "$_default_page";
	private static final String EXCLUDE_PATH = "excludePath";

	private List<Pattern> excludePatterns = new ArrayList<Pattern>();

	@Override
	public void destroy() {
	}

	public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
			throws IOException, ServletException {
		try {
			HttpServletRequest request = (HttpServletRequest) servletRequest;
			HttpServletResponse response = (HttpServletResponse) servletResponse;
			String servletPath = getServletPath(request);
			if (isExcluded(servletPath)) {
				// 请求路径被拒绝
				filterChain.doFilter(request, response);
				return;
			}
			WebContext context = new WebContextImpl();
			context.put("context", context);
			putRequestInfo(request, context);
			context.init(request, response, request.getServletContext());
			FilterHandler handler = new FilterHandler(servletPath, filterChain, context, null);
			handler.handle(request, response);
		} finally {
		}
	}

	private String getServletPath(HttpServletRequest request) {
		String servletPath = request.getServletPath();
		if (StringUtils.isBlank(servletPath)) {
			servletPath = request.getPathInfo();
		}
		if (StringUtils.isBlank(servletPath)) {// 兼容tomcat8的处理情况，如果servletPath为空，设置为"/"
			servletPath = "/";
		}
		return servletPath;
	}

	private void putRequestInfo(HttpServletRequest request, WebContext context) {
		String path = request.getContextPath();
		if (path == null) {
			path = "";
		}
		context.put(TINY_CONTEXT_PATH, path);
		context.put(TINY_REQUEST_URI, request.getRequestURI());
		String servletPath = request.getServletPath();
		if (servletPath == null || servletPath.length() == 0) {
			servletPath = request.getPathInfo();
		}
		context.put(TINY_SERVLET_PATH, servletPath);
	}

	/**
	 * 请求是否被排除
	 * 
	 * @param servletPath
	 * @return
	 */
	private boolean isExcluded(String servletPath) {
		for (Pattern pattern : excludePatterns) {
			if (pattern.matcher(servletPath).matches()) {
				return true;
			}
		}
		return false;
	}

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		initExcludePattern(filterConfig);
	}

	private void initExcludePattern(FilterConfig filterConfig) {
		excludePatterns.clear();// 先清空
		String excludePath = filterConfig.getInitParameter(EXCLUDE_PATH);
		if (excludePath != null) {
			String[] excludeArray = excludePath.split(",");
			for (String path : excludeArray) {
				excludePatterns.add(Pattern.compile(path));
			}
		}
	}

}
